﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SscLib
{
    public class Context
    {
        Stack<ScopeSymbol> scopes = new Stack<ScopeSymbol>();
        Stack<bool> remotes = new Stack<bool>();

        Stack<TypeSymbol> types = new Stack<TypeSymbol>();
        Stack<MethodSymbolBase> methods = new Stack<MethodSymbolBase>();

        public MethodSymbolBase CurrentMethod
        {
            get { return methods.Peek(); }
        }

        public TypeSymbol CurrentType
        {
            get { return types.Peek(); }
        }

        public bool Remote
        {
            get { return remotes.Peek(); }
        }

        public ScopeSymbol Scope
        {
            get { return scopes.Peek(); }
        }

        public void Push(ScopeSymbol scope)
        {
            Push(scope, false);
        }

        public void Push(ScopeSymbol scope, bool remote)
        {
            scopes.Push(scope);
            remotes.Push(remote);

            if (!remote)
            {
                if (scope is TypeSymbol) types.Push(scope as TypeSymbol);
                if (scope is MethodSymbolBase) methods.Push(scope as MethodSymbolBase);
            }
        }

        public ScopeSymbol Pop()
        {
            bool remote = remotes.Pop();
            ScopeSymbol scope = scopes.Pop();

            if (!remote)
            {
                if (scope is TypeSymbol) types.Pop();
                if (scope is MethodSymbolBase) methods.Pop();
            }
            return scope;
        }

        public object PopRemotes()
        {
            Stack<ScopeSymbol> temp = null;
            if (this.Remote)
            {
                temp = new Stack<ScopeSymbol>();

                while (this.Remote)
                {
                    temp.Push(this.Pop());
                }

            }
            return temp;
        }

        public void PushRemotes(object r)
        {
            if (r != null)
            {
                Stack<ScopeSymbol> temp = r as Stack<ScopeSymbol>;

                while (temp.Count > 0)
                {
                    this.Push(temp.Pop(), true);
                }
            }
        }

        public System.Reflection.Emit.ILGenerator IL
        {
            get { return CurrentMethod.ILGenerator; }
        }
    }
}
